package cn.yx.common.web.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.yx.common.core.constant.MdcConstant;
import cn.yx.common.core.enums.http.HttpHeaderCustomEnum;
import cn.yx.common.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * <p>日志拦截器类，使用MDC记录请求事务ID到日志</p>
 *
 * @author Wgssmart
 */
@Slf4j
public class LoggerInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String transactionId = getTransactionId(request);
        // 把transactionId放入到request的attribute，方便在AppResponseBodyAdvice中获取
        request.setAttribute(HttpHeaderCustomEnum.TRANSACTION_ID.getName(), transactionId);
        MDC.put(MdcConstant.TRACE_ID, transactionId);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        MDC.clear();
    }

    /**
     * 获取transactionId，先从请求头中获取，如果请求头中没有transactionId，则直接生成transactionId
     *
     * @param request
     * @return
     */
    private String getTransactionId(HttpServletRequest request) {
        // 由gateway路由的请求，transactionId在请求头，或可直接在前端传递transactionId
        String transactionId = request.getHeader(HttpHeaderCustomEnum.TRANSACTION_ID.getName());
        if (StrUtil.isNotEmpty(transactionId)) {
            return transactionId;
        }
        return IdUtil.id();
    }
}
